/*!	 paramdesc.h
**	 ParamDesc Class Implementation
**
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**
*/

#ifndef __SYNFIG_PARAMDESC_H
#define __SYNFIG_PARAMDESC_H

#include "string.h"
#include "real.h"
#include "color.h"
#include "interpolation.h"
#include <list>

namespace synfig
{

class ValueBase;

/*!	\class ParamDesc
**	 Parameter Description Class
**	TODO:  writeme
*/
class ParamDesc
{
public:

    // \writeme
    struct EnumData {
        int value;
        String name;
        String local_name;
        EnumData(int value, const String &name, const String &local_name):
            value(value),
            name(name),
            local_name(local_name)
        {
        }
    };



private:
    String name_;			// The actual parameter name
    String local_name_; 	// Localized name
    String desc_;			// Short description of parameter (Think tooltops)
    String group_;			// Which group this parameter is a member of (optional)
    String hint_;			// Parameter hint
    String origin_;			// Parameter origin
    String connect_;
    String box_;
    Real scalar_;			// Scalar value for visual editing
    bool exponential_;		// Allow range from -inf to inf for visual editing
    bool critical_;
    bool hidden_;
    bool invisible_duck_;
    bool is_distance_;
    bool animation_only_;
    bool static_;
    Interpolation interpolation_;

    std::list<EnumData> enum_list_;



public:

    ParamDesc(const String &a = "IM_A_BUG_SO_REPORT_ME"):
        name_(a),
        local_name_(a),
        scalar_(1.0),
        exponential_(false),
        critical_(true),
        hidden_(false),
        invisible_duck_(false),
        is_distance_(false),
        animation_only_(false),
        static_(false),
        interpolation_(INTERPOLATION_UNDEFINED)
    { }

    ParamDesc(const ValueBase&, const String &a);

    ParamDesc(const String &name, const ParamDesc &blank)
    {
        *this = blank;
        name_ = name;
    }



public:

    // \writeme
    const std::list<EnumData> &get_enum_list()const
    {
        return enum_list_;
    }

    // Sets the localized name of the parameter.
    ParamDesc &set_local_name(const String &n)
    {
        local_name_ = n;
        return *this;
    }

    // Sets the localized description of the parameter.
    ParamDesc &set_description(const String &d)
    {
        desc_ = d;
        return *this;
    }

    // Sets the group that this parameter is a member of
    ParamDesc &set_group(const String &n)
    {
        group_ = n;
        return *this;
    }

    // Sets a "hint" for the parameter.
    ParamDesc &set_hint(const String &h)
    {
        hint_ = h;
        return *this;
    }

    // \writeme
    ParamDesc &set_connect(const String &h)
    {
        connect_ = h;
        return *this;
    }

    // \writeme
    ParamDesc &set_box(const String &h)
    {
        box_ = h;
        return *this;
    }

    // Sets a flag regarding the duck visibility
    ParamDesc &set_invisible_duck(bool x = true)
    {
        invisible_duck_ = x;
        return *this;
    }

    // Returns the flag regarding duck visibility
    bool get_invisible_duck()
    {
        return invisible_duck_;
    }

    // \writeme
    ParamDesc &set_animation_only(bool x = true)
    {
        animation_only_ = x;
        return *this;
    }

    // \writeme
    bool get_animation_only()
    {
        return animation_only_;
    }

    // Sets which parameter is to be used as the origin when the user edits visually.
    ParamDesc &set_origin(const String &h)
    {
        origin_ = h;
        return *this;
    }

    // Sets the scalar value for the parameter
    /*! This value determines how the value is to be presented
    **	to the user when editing visually. */
    ParamDesc &set_scalar(const Real &n)
    {
        scalar_ = n;
        return *this;
    }

    // Sets if the parameter value should be exposed for visual editing using the exponential function
    /*!	Such representation allows to set the Real values in the range from \c -inf to \c inf . */
    ParamDesc &set_exponential(bool x = true)
    {
        exponential_ = x;
        return *this;
    }

    //	Marks the parameter as not necessary for saving or copying
    ParamDesc &not_critical()
    {
        critical_ = false;
        return *this;
    }

    //	\writeme
    ParamDesc &hidden()
    {
        hidden_ = true;
        return *this;
    }

    //	Marks the parameter as only readable. Implies not_critical()
    /*!	TODO:  This function needs to be written, as it is only a stub */
    ParamDesc &read_only()
    {
        return *this;
    }

    //	Marks the parameter as only writable. Implies not_critical()
    /*!	TODO:  This function needs to be written, as it is only a stub */
    ParamDesc &write_only()
    {
        return *this;
    }

    // Adds a description of a possible enumeration value
    /*!	Only relevant if the parameter is of an integer type and hint set to \c "enum" . */
    ParamDesc &add_enum_value(int val, const String &enum_name, const String &enum_local_name)
    {
        enum_list_.push_back(EnumData(val, enum_name, enum_local_name));
        return *this;
    }

    // Returns the localized name of the parameter
    const String &get_local_name()const
    {
        return local_name_;
    }

    // Returns the name of the parameter
    const String &get_name()const
    {
        return name_;
    }

    // Returns the localized description of the parameter
    const String &get_description()const
    {
        return desc_;
    }

    // Returns the parameter's group
    const String &get_group()const
    {
        return group_;
    }

    // Returns a "hint" about the parameter, regarding how it is to be displayed to the user
    const String &get_hint()const
    {
        return hint_;
    }

    // Returns the name of the parameter that is defined as the "origin". Used for visual editing.
    const String &get_origin()const
    {
        return origin_;
    }

    // \writeme
    const String &get_connect()const
    {
        return connect_;
    }

    // \writeme
    const String &get_box()const
    {
        return box_;
    }

    // Returns the scalar value for the parameter. Used for visual editing.
    const Real &get_scalar()const
    {
        return scalar_;
    }

    // Tells if the value should be exposed for editing using the exponential function
    /*!	Such representation allows to set the Real values in the range from \c -inf to \c inf . */
    bool get_exponential()const
    {
        return exponential_;
    }

    // Returns \c true if the layer is critical, \c false otherwise.
    bool get_critical()const
    {
        return critical_;
    }

    // Returns \c true if the layer is hidden, \c false otherwise.
    bool get_hidden()const
    {
        return hidden_;
    }

    bool get_static()const
    {
        return static_;
    }
    ParamDesc &set_static(bool s)
    {
        static_ = s;
        return *this;
    }

    Interpolation get_interpolation()const
    {
        return interpolation_;
    }
    ParamDesc &set_interpolation(Interpolation i)
    {
        interpolation_ = i;
        return *this;
    }

    ParamDesc& set_is_distance(bool x = true)
    {
        is_distance_ = x;
        return *this;
    }
    bool get_is_distance()const
    {
        return is_distance_;
    }
}; // END of class ParamDesc

class ParamVocab : public std::list< ParamDesc >
{
private:
    static const ParamDesc blank;

public:
    const ParamDesc& operator[](const String &name) const
    {
        for (const_iterator i = begin(); i != end(); ++i)
            if (i->get_name() == name) {
                return *i;
            }

        assert(false);
        return blank;
    }
};

}; // END of namespace synfig

#endif